{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 使用聚类解决Event Recommendation Engine Challenge"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1 用户和活动关联关系处理\n",
    "整个数据集中活动数目（events.csv）太多，所以下面的处理我们找出只在训练集和测试集中出现的活动和用户集合，并对他们重新编制索引"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.1 读取数据，分析数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "#保存数据\n",
    "import pickle\n",
    "\n",
    "import itertools\n",
    "\n",
    "#处理事件字符串\n",
    "import datetime\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd \n",
    "import scipy.io as sio\n",
    "import scipy.sparse as ss\n",
    "\n",
    "#相似度/距离\n",
    "import scipy.spatial.distance as ssd\n",
    "\n",
    "from collections import defaultdict\n",
    "from sklearn.preprocessing import normalize"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "number of uniqueUsers :3391\n",
      "number of uniqueEvents :13418\n"
     ]
    }
   ],
   "source": [
    "\"\"\"\n",
    "我们只关心train和test中出现的user和event，因此重点处理这部分关联数据\n",
    "\n",
    "train.csv 有6列：\n",
    "user：用户ID\n",
    "event：活动ID\n",
    "invited：是否被邀请（0/1）\n",
    "timestamp：ISO-8601 UTC格式时间字符串，表示用户看到该活动的时间\n",
    "interested, and not_interested\n",
    "\n",
    "Test.csv 除了没有interested, and not_interested，其余列与train相同\n",
    " \"\"\"\n",
    "    \n",
    "# 统计训练集中有多少不同的用户的events\n",
    "uniqueUsers = set()\n",
    "uniqueEvents = set()\n",
    "\n",
    "#倒排表\n",
    "#统计每个用户参加的活动   / 每个活动参加的用户\n",
    "eventsForUser = defaultdict(set)\n",
    "usersForEvent = defaultdict(set)\n",
    "    \n",
    "for filename in [\"train.csv\", \"test.csv\"]:\n",
    "    f = open(filename, 'r')\n",
    "\n",
    "    #忽略第一行（列名字）\n",
    "    f.readline().strip().split(\",\")\n",
    "    \n",
    "    for line in f:    #对每条记录\n",
    "        cols = line.strip().split(\",\")\n",
    "        uniqueUsers.add(cols[0])   #第一列为用户ID\n",
    "        uniqueEvents.add(cols[1])   #第二列为活动ID\n",
    "        \n",
    "        #eventsForUser[cols[0]].add(cols[1])    #该用户参加了这个活动\n",
    "        #usersForEvent[cols[1]].add(cols[0])    #该活动被用户参加\n",
    "    f.close()\n",
    "\n",
    "\n",
    "n_uniqueUsers = len(uniqueUsers)\n",
    "n_uniqueEvents = len(uniqueEvents)\n",
    "\n",
    "print(\"number of uniqueUsers :%d\" % n_uniqueUsers)\n",
    "print(\"number of uniqueEvents :%d\" % n_uniqueEvents)\n",
    "\n",
    "#用户关系矩阵表，可用于后续LFM/SVD++处理的输入\n",
    "#这是一个稀疏矩阵，记录用户对活动感兴趣\n",
    "userEventScores = ss.dok_matrix((n_uniqueUsers, n_uniqueEvents))\n",
    "userIndex = dict()\n",
    "eventIndex = dict()\n",
    "\n",
    "#重新编码用户索引字典\n",
    "for i, u in enumerate(uniqueUsers):\n",
    "    userIndex[u] = i\n",
    "    \n",
    "#重新编码活动索引字典    \n",
    "for i, e in enumerate(uniqueEvents):\n",
    "    eventIndex[e] = i\n",
    "\n",
    "n_records = 0\n",
    "ftrain = open(\"train.csv\", 'r')\n",
    "ftrain.readline()\n",
    "for line in ftrain:\n",
    "    cols = line.strip().split(\",\")\n",
    "    i = userIndex[cols[0]]  #用户\n",
    "    j = eventIndex[cols[1]] #活动\n",
    "    \n",
    "    eventsForUser[i].add(j)    #该用户参加了这个活动\n",
    "    usersForEvent[j].add(i)    #该活动被用户参加\n",
    "        \n",
    "    #userEventScores[i, j] = int(cols[4]) - int(cols[5])   #interested - not_interested\n",
    "    score = int(cols[4])\n",
    "    #if score == 0:  #0在稀疏矩阵中表示该元素不存在，因此借用-1表示interested=0\n",
    "    #userEventScores[i, j] = -1\n",
    "    #else:\n",
    "    userEventScores[i, j] = score\n",
    "ftrain.close()\n",
    "\n",
    "  \n",
    "##统计每个用户参加的活动，后续用于将用户朋友参加的活动影响到用户\n",
    "pickle.dump(eventsForUser, open(\"PE_eventsForUser.pkl\", 'wb'))\n",
    "##统计活动参加的用户\n",
    "pickle.dump(usersForEvent, open(\"PE_usersForEvent.pkl\", 'wb'))\n",
    "\n",
    "#保存用户-活动关系矩阵R，以备后用\n",
    "sio.mmwrite(\"PE_userEventScores\", userEventScores)\n",
    "\n",
    "\n",
    "#保存用户索引表\n",
    "pickle.dump(userIndex, open(\"PE_userIndex.pkl\", 'wb'))\n",
    "#保存活动索引表\n",
    "pickle.dump(eventIndex, open(\"PE_eventIndex.pkl\", 'wb'))\n",
    "\n",
    "    \n",
    "# 为了防止不必要的计算，我们找出来所有关联的用户 或者 关联的event\n",
    "# 所谓的关联用户，指的是至少在同一个event上有行为的用户pair\n",
    "# 关联的event指的是至少同一个user有行为的event pair\n",
    "uniqueUserPairs = set()\n",
    "uniqueEventPairs = set()\n",
    "for event in uniqueEvents:\n",
    "    i = eventIndex[event]\n",
    "    users = usersForEvent[i]\n",
    "    if len(users) > 2:\n",
    "        uniqueUserPairs.update(itertools.combinations(users, 2))\n",
    "        \n",
    "for user in uniqueUsers:\n",
    "    u = userIndex[user]\n",
    "    events = eventsForUser[u]\n",
    "    if len(events) > 2:\n",
    "        uniqueEventPairs.update(itertools.combinations(events, 2))\n",
    " \n",
    "#保存用户-事件关系对索引表\n",
    "pickle.dump(uniqueUserPairs, open(\"FE_uniqueUserPairs.pkl\", 'wb'))\n",
    "pickle.dump(uniqueEventPairs, open(\"PE_uniqueEventPairs.pkl\", 'wb'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 训练集和测试集中出现的用户数目和事件数目远小于users.csv出现的用户数和events.csv出现的事件数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.2 抽取出只在训练集和测试集中出现的event"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_uniqueEvents = pd.read_csv('train.csv',usecols=['event','user'])\n",
    "test_uniqueEvents = pd.read_csv('test.csv',usecols=['event','user'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2 对event进行聚类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "#导入必要的工具包\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn.cluster import MiniBatchKMeans\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn import metrics\n",
    "\n",
    "\n",
    "import time\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "n_trains = 10000\n",
    "\n",
    "X_train = train_uniqueEvents.drop(\"user\",axis=1).values[:n_trains]\n",
    "X_val = test_uniqueEvents.drop(\"user\",axis=1).values[:n_trains]\n",
    "\n",
    "y_train = train_uniqueEvents.user.values[:n_trains]\n",
    "y_val = test_uniqueEvents.user.values[:n_trains]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "#将像素值[0,5000000000]  --> [0,1]\n",
    "X_train = X_train / 5000000000.0\n",
    "X_val = X_val / 50000000.0\n",
    "y_train = y_train / 5000000000.0\n",
    "y_val = y_val / 50000000.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(10000, 1)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(10000, 1)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_val.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def K_cluster_analysis(K, X_train, y_train, X_val, y_val):\n",
    "    start = time.time()\n",
    "    \n",
    "    print(\"K-means begin with clusters: {}\".format(K));\n",
    "    \n",
    "    #K-means,在训练集上训练\n",
    "    mb_kmeans = MiniBatchKMeans(n_clusters = K)\n",
    "    mb_kmeans.fit(X_train)\n",
    "    \n",
    "    # 在训练集和测试集上测试\n",
    "    #y_train_pred = mb_kmeans.fit_predict(X_train)\n",
    "    y_val_pred = mb_kmeans.predict(X_val)\n",
    "    \n",
    "    #以前两维特征打印训练数据的分类结果\n",
    "    #plt.scatter(X_train[:, 0], X_train[:, 1], c=y_pred)\n",
    "    #plt.show()\n",
    "\n",
    "    # K值的评估标准\n",
    "    #常见的方法有轮廓系数Silhouette Coefficient和Calinski-Harabasz Index\n",
    "    #这两个分数值越大则聚类效果越好\n",
    "    #CH_score = metrics.calinski_harabaz_score(X_train,mb_kmeans.predict(X_train))\n",
    "    CH_score = metrics.silhouette_score(X_train,mb_kmeans.predict(X_train))\n",
    "    \n",
    "    #也可以在校验集上评估K\n",
    "    v_score = metrics.v_measure_score(y_val, y_val_pred)\n",
    "    \n",
    "    end = time.time()\n",
    "    print(\"CH_score: {}, time elaps:{}\".format(CH_score, int(end-start)))\n",
    "    print(\"v_score: {}\".format(v_score))\n",
    "    \n",
    "    return CH_score,v_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "K-means begin with clusters: 10\n",
      "CH_score: 0.5353261064142495, time elaps:3\n",
      "v_score: 0.007749308531946338\n",
      "K-means begin with clusters: 70\n",
      "CH_score: 0.5603630268573577, time elaps:3\n",
      "v_score: 0.010650243871740957\n",
      "K-means begin with clusters: 130\n",
      "CH_score: 0.5905794041994025, time elaps:4\n",
      "v_score: 0.010711102697094679\n",
      "K-means begin with clusters: 190\n",
      "CH_score: 0.5937471888545581, time elaps:5\n",
      "v_score: 0.010843725552042223\n",
      "K-means begin with clusters: 250\n",
      "CH_score: 0.5986842775272722, time elaps:7\n",
      "v_score: 0.010998483800777724\n",
      "K-means begin with clusters: 310\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\hplxg\\Anaconda3\\envs\\python3\\lib\\site-packages\\sklearn\\cluster\\k_means_.py:1418: RuntimeWarning: init_size=300 should be larger than k=310. Setting it to 3*k\n",
      "  init_size=init_size)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CH_score: 0.604502799398105, time elaps:11\n",
      "v_score: 0.011061252926697912\n",
      "K-means begin with clusters: 370\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\hplxg\\Anaconda3\\envs\\python3\\lib\\site-packages\\sklearn\\cluster\\k_means_.py:1418: RuntimeWarning: init_size=300 should be larger than k=370. Setting it to 3*k\n",
      "  init_size=init_size)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CH_score: 0.6284396552361472, time elaps:12\n",
      "v_score: 0.011046651743776163\n",
      "K-means begin with clusters: 430\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\hplxg\\Anaconda3\\envs\\python3\\lib\\site-packages\\sklearn\\cluster\\k_means_.py:1418: RuntimeWarning: init_size=300 should be larger than k=430. Setting it to 3*k\n",
      "  init_size=init_size)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CH_score: 0.6400277517844343, time elaps:12\n",
      "v_score: 0.011167817589043333\n",
      "K-means begin with clusters: 490\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\hplxg\\Anaconda3\\envs\\python3\\lib\\site-packages\\sklearn\\cluster\\k_means_.py:1418: RuntimeWarning: init_size=300 should be larger than k=490. Setting it to 3*k\n",
      "  init_size=init_size)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CH_score: 0.6329276982256093, time elaps:17\n",
      "v_score: 0.01115321797070889\n",
      "K-means begin with clusters: 550\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\hplxg\\Anaconda3\\envs\\python3\\lib\\site-packages\\sklearn\\cluster\\k_means_.py:1418: RuntimeWarning: init_size=300 should be larger than k=550. Setting it to 3*k\n",
      "  init_size=init_size)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CH_score: 0.61085603929019, time elaps:16\n",
      "v_score: 0.011143736843425242\n"
     ]
    }
   ],
   "source": [
    "Ks = [10,70,130,190,250,310,370,430,490,550]\n",
    "CH_scores = []\n",
    "v_scores = []\n",
    "for K in Ks:\n",
    "    ch,v = K_cluster_analysis(K,X_train, y_train, X_val, y_val)\n",
    "    CH_scores.append(ch)\n",
    "    v_scores.append(v)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x2960a976fd0>]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x296088d9780>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 绘制不同PCA维数下模型的性能，找到最佳模型／参数（分数最高）\n",
    "plt.plot(Ks, np.array(CH_scores), 'b-')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x2960aa0f518>]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x2960a9431d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(Ks, np.array(v_scores), 'g-')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x2960aa45320>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#显示聚类结果\n",
    "#画出聚类结果，每一类用一种颜色\n",
    "colors = ['b','g','r','k','c','m','y','#e24fff','#524C90','#845868']\n",
    "\n",
    "n_clusters = 10\n",
    "mb_kmeans = MiniBatchKMeans(n_clusters = n_clusters)\n",
    "mb_kmeans.fit(X_train)\n",
    "\n",
    "y_train_pred = mb_kmeans.labels_\n",
    "cents = mb_kmeans.cluster_centers_#质心\n",
    "\n",
    "for i in range(n_clusters):\n",
    "    index = np.nonzero(y_train_pred==i)[0]\n",
    "    x1 = X_train[index,0]\n",
    "    y_i = y_train[index]\n",
    "    for j in range(len(x1)):\n",
    "        if j < 20:  #每类打印20个\n",
    "            plt.text(x1[j],j,str(int(y_i[j])),color=colors[i],\\\n",
    "                fontdict={'weight': 'bold', 'size': 9})\n",
    "    #plt.scatter(cents[i,0],cents[i,1],marker='x',color=colors[i],linewidths=12)\n",
    "\n",
    "plt.axis([-0.3,1,-0.3,22])\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
